package com.oromwin.repos.socket.request.file;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.List;

import org.apache.commons.logging.Log;

import com.oromwin.repos.common.Common;
import com.oromwin.repos.common.Logger;
import com.oromwin.repos.common.ReposException;
import com.oromwin.repos.common.Common.ReposResult;
import com.oromwin.repos.common.Common.Status;
import com.oromwin.repos.common.helper.DBHelper;
import com.oromwin.repos.common.helper.FSHelper;
import com.oromwin.repos.common.helper.IOHelper;
import com.oromwin.repos.data.AbstractReposTable;
import com.oromwin.repos.data.FileTable;
import com.oromwin.repos.server.LockObject;
import com.oromwin.repos.socket.request.AbstractRequest;
import com.oromwin.repos.socket.request.RequestAction;
import com.oromwin.repos.socket.response.Response;
import com.oromwin.repos.socket.response.file.DeleteFileResponse;

public class DeleteFileRequest extends AbstractRequest implements RequestAction {
    private Log log = Logger.getLog(DeleteFileRequest.class);
    private String VolumeName = null;
    private String FileId = null;
    private boolean _force = false;
    
    public DeleteFileRequest() {
    }
    
    public DeleteFileRequest(String volumeName, String fileId, boolean force) {
        VolumeName = volumeName;
        FileId = fileId;
        _force = force;
    }
    
    @Override
    public void receive(DataInputStream dis, LockObject lockObject) throws ReposException {
        try {
            synchronized (lockObject) {
                VolumeName = IOHelper.readUTF8(dis);
                FileId = IOHelper.readUTF8(dis);
                _force = dis.readBoolean();
                _fileTable = (FileTable) getCurrentReposTable();
            }
        } catch (IOException e) {
            String message = String.format("Failed to read stream, {%s}", e.getMessage());
            throw ReposException.create(log, e, message);
        }
    }

    @Override
    public Response run() {
        DeleteFileResponse res = null;
        try {
            checkSameObjectExists();
            String whereClause = String.format("FileId = '%s'", FileId);
            if (_force) {
                DBHelper.deleteTable(FileTable.class, whereClause);
                FSHelper.delete(_fileTable.getFullFilepath());
            } else {
                _fileTable.setFileStatus(Status.DELETE.ordinal());
                DBHelper.updateTable(_fileTable, whereClause);
            }
            res = new DeleteFileResponse(ReposResult.Success, "Succeeded to delete file");
        } catch (ReposException e) {
            res = new DeleteFileResponse(ReposResult.Failure, e.getMessage());
        }
        return res;
    }

    @Override
    public void send(DataOutputStream dos) throws ReposException {
        try {
            IOHelper.writeUTF8(dos, this.getClass().getCanonicalName());
            IOHelper.writeUTF8(dos, VolumeName);
            IOHelper.writeUTF8(dos, FileId);
            dos.writeBoolean(_force);
            dos.flush();
        } catch (IOException e) {
            String message = String.format("Failed to read object input stream from server, {%s}", e.getMessage());
            throw ReposException.create(log, e, message);
        }
    }

    @Override
    public void checkFreeSpaceExists() throws ReposException {
        throw ReposException.create(log, Common.Message.NOT_IMPLEMENTED_METHOD_INVOKE);
    }

    @Override
    public void checkSameObjectExists() throws ReposException {
        File file = _fileTable.getFullFilepath();
        if (!FSHelper.ls(file)) {
            String message = String.format("'%s' FilePath does not exists", file);
            throw ReposException.create(log, message);
        }
    }

    @Override
    public void checkDependentObjectNotExists() throws ReposException {
        throw ReposException.create(log, Common.Message.NOT_IMPLEMENTED_METHOD_INVOKE);
    }

    @Override
    public AbstractReposTable getCurrentReposTable() throws ReposException {
        AbstractReposTable reposTable = null;
        String whereClause = String.format("FileStatus < 2 AND FileId = '%s'", FileId);
        List<AbstractReposTable> reposTables = DBHelper.selectTable(FileTable.class, whereClause);
        if (reposTables != null && reposTables.size() == 1) {
            reposTable = reposTables.get(0);
        } else {
            String message = String.format("'%s' FileId does not exists in database, VolumeName:tableSize:whereClause {%s:%d:%s}", FileId, VolumeName, reposTables.size(), whereClause);
            throw ReposException.create(log, message); 
        }
        return reposTable;
    }

    @Override
    public AbstractReposTable getParentReposTable() throws ReposException {
        throw ReposException.create(log, Common.Message.NOT_IMPLEMENTED_METHOD_INVOKE);
    }

}
